package org.phoenixframework.api.sys.controller;


import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.json.JSONUtil;
import io.minio.*;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.phoenixframework.api.sys.config.spring.MinioProperties;
import org.phoenixframework.api.sys.service.ISysFileService;
import org.phoenixframework.common.entity.SysFile;
import org.phoenixframework.common.entity.annotation.OperationLog;
import org.phoenixframework.common.entity.dto.BucketPolicyConfigDto;
import org.phoenixframework.common.tools.ResultModel;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.util.Date;

/**
 * <p>
 * 文件表 前端控制器
 * </p>
 *
 * @author doublelife
 * @since 2021-07-03
 */
@Slf4j
@Api(tags = {"文件存储管理"})
@AllArgsConstructor
@RestController
@RequestMapping("/sysFile")
public class SysFileController extends BaseController {

    private final ISysFileService sysFileService;

    private final MinioProperties minioProperties;

    private BucketPolicyConfigDto createBucketPolicyConfigDto(String bucketName) {
        BucketPolicyConfigDto.Statement statement = BucketPolicyConfigDto.Statement.builder()
                .effect("Allow")
                .principal("*")
                .action("s3:GetObject")
                .resource("arn:aws:s3:::" + bucketName + "/*.**").build();
        return BucketPolicyConfigDto.builder()
                .version(DateUtil.formatDate(new Date()))
                .statement(CollUtil.toList(statement))
                .build();
    }

    @OperationLog
    @ApiOperation("文件上传")
    @PostMapping("/upload")
    public ResultModel<?> upload(@RequestParam("file") MultipartFile file) {
        // 创建一个MinIO的Java客户端
        try {
            MinioClient minioClient = MinioClient.builder()
                    .endpoint(minioProperties.getEndpoint())
                    .credentials(minioProperties.getAccessKey(), minioProperties.getSecretKey())
                    .build();
            boolean isExist = minioClient.bucketExists(BucketExistsArgs.builder().bucket(minioProperties.getBucketName()).build());

            if (isExist) {
                log.info("存储桶已经存在！");
            } else {
                //创建存储桶并设置只读权限
                minioClient.makeBucket(MakeBucketArgs.builder().bucket(minioProperties.getBucketName()).build());
                BucketPolicyConfigDto bucketPolicyConfigDto = createBucketPolicyConfigDto(minioProperties.getBucketName());
                SetBucketPolicyArgs setBucketPolicyArgs = SetBucketPolicyArgs.builder()
                        .bucket(minioProperties.getBucketName())
                        .config(JSONUtil.toJsonStr(bucketPolicyConfigDto))
                        .build();
                minioClient.setBucketPolicy(setBucketPolicyArgs);
            }
            String filename = file.getOriginalFilename();
            // 设置存储对象名称
            String objectName = DateUtil.formatDate(new Date()) + "/" + filename;
            // 使用putObject上传一个文件到存储桶中
            PutObjectArgs putObjectArgs = PutObjectArgs.builder()
                    .bucket(minioProperties.getBucketName())
                    .object(objectName)
                    .contentType(file.getContentType())
                    .stream(file.getInputStream(), file.getSize(), ObjectWriteArgs.MIN_MULTIPART_SIZE).build();
            minioClient.putObject(putObjectArgs);
            log.info("文件上传成功!");
            SysFile sysFile = new SysFile();
            sysFile.setName(filename);
            sysFile.setFilename(filename);
            sysFile.setObjectName(objectName);
            sysFile.setPath(minioProperties.getEndpoint() + "/" + minioProperties.getBucketName() + "/" + objectName);
            sysFile.setSize(file.getSize());
            boolean save = sysFileService.save(sysFile);
            return buildByBool(save);
        } catch (Exception e) {
            return ResultModel.error("上传发生错误！");
        }
    }

    @OperationLog
    @ApiOperation("根据id删除一条信息")
    @DeleteMapping("/remove/{id}")
    public ResultModel<?> removeById(@ApiParam(name = "id", value = "对象信息id", required = true) @PathVariable Long id) {
        try {
            MinioClient minioClient = MinioClient.builder()
                    .endpoint(minioProperties.getEndpoint())
                    .credentials(minioProperties.getAccessKey(), minioProperties.getSecretKey())
                    .build();
            SysFile sysFile = sysFileService.getById(id);
            // objectName 存储对象名称
            minioClient.removeObject(RemoveObjectArgs.builder().bucket(minioProperties.getBucketName()).object(sysFile.getObjectName()).build());
            boolean b = sysFileService.removeById(id);
            return buildByBool(b);
        } catch (Exception e) {
            return ResultModel.error("删除文件发生错误！");
        }
    }

}
